package com.mcc.app.energy.service.impl;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mcc.app.cache.domain.HisCol;
import com.mcc.app.cache.domain.PlcCache;
import com.mcc.app.cache.service.IPlcCacheService;
import com.mcc.common.annotation.DataSource;
import com.mcc.common.config.ProjectConfig;
import com.mcc.common.enums.DataSourceType;
import com.mcc.common.exception.CustomException;
import com.mcc.common.utils.uuid.IdUtils;
import com.mcc.framework.datasource.DynamicDataSourceContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mcc.app.energy.mapper.EnergyPwaterStatisitcsMapper;
import com.mcc.app.energy.domain.EnergyPwaterStatisitcs;
import com.mcc.app.energy.service.IEnergyPwaterStatisitcsService;

import static com.mcc.common.utils.file.FileUploadUtils.getAbsoluteFile;

/**
 * 能源水泵用水量统计Service业务层处理
 *
 * @author gxy
 * @date 2025-03-25
 */
@Service
public class EnergyPwaterStatisitcsServiceImpl implements IEnergyPwaterStatisitcsService {

    @Autowired
    private EnergyPwaterStatisitcsMapper energyPwaterStatisitcsMapper;

    @Autowired
    private IPlcCacheService plcCacheService;

    /**
     * 查询能源水泵用水量统计
     *
     * @param id 能源水泵用水量统计ID
     * @return 能源水泵用水量统计
     */
    @Override
    public EnergyPwaterStatisitcs selectEnergyPwaterStatisitcsById(Long id) {
        return energyPwaterStatisitcsMapper.selectById(id);
    }

    /**
     * 查询能源水泵用水量统计列表
     *
     * @param energyPwaterStatisitcs 能源水泵用水量统计
     * @return 能源水泵用水量统计
     */
    @Override
    public List<EnergyPwaterStatisitcs> selectEnergyPwaterStatisitcsList(EnergyPwaterStatisitcs energyPwaterStatisitcs) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (ObjectUtil.isNotEmpty(energyPwaterStatisitcs)) {
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getTime()), "time", energyPwaterStatisitcs.getTime());
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getTableType()), "table_type", energyPwaterStatisitcs.getTableType());
            queryWrapper.like(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getGroupName()), "group_name", energyPwaterStatisitcs.getGroupName());
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getGroupNo()), "group_no", energyPwaterStatisitcs.getGroupNo());
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getPumpwater1()), "pumpwater1", energyPwaterStatisitcs.getPumpwater1());
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getPumpwater2()), "pumpwater2", energyPwaterStatisitcs.getPumpwater2());
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getPumpwater3()), "pumpwater3", energyPwaterStatisitcs.getPumpwater3());
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getPumpwater4()), "pumpwater4", energyPwaterStatisitcs.getPumpwater4());
            queryWrapper.eq(ObjectUtil.isNotEmpty(energyPwaterStatisitcs.getPumpwater5()), "pumpwater5", energyPwaterStatisitcs.getPumpwater5());
        }
        return energyPwaterStatisitcsMapper.selectList(queryWrapper);
    }

    /**
     * 新增能源水泵用水量统计
     *
     * @param energyPwaterStatisitcs 能源水泵用水量统计
     * @return 结果
     */
    @Override
    public int insertEnergyPwaterStatisitcs(EnergyPwaterStatisitcs energyPwaterStatisitcs) {
        return energyPwaterStatisitcsMapper.insert(energyPwaterStatisitcs);
    }

    /**
     * 修改能源水泵用水量统计
     *
     * @param energyPwaterStatisitcs 能源水泵用水量统计
     * @return 结果
     */
    @Override
    public int updateEnergyPwaterStatisitcs(EnergyPwaterStatisitcs energyPwaterStatisitcs) {
        return energyPwaterStatisitcsMapper.updateById(energyPwaterStatisitcs);
    }

    /**
     * 删除能源水泵用水量统计
     *
     * @param id 能源水泵用水量统计ID
     * @return 结果
     */
    @Override
    public int deleteEnergyPwaterStatisitcsById(Long id) {
        return energyPwaterStatisitcsMapper.deleteById(id);
    }

    /**
     * 批量删除能源水泵用水量统计
     *
     * @param ids 能源水泵用水量统计ID
     * @return 结果
     */
    @Override
    public int deleteEnergyPwaterStatisitcsByIds(Long[] ids) {
        if (ids.length == 0) return 0;
        return energyPwaterStatisitcsMapper.deleteBatchIds(ListUtil.toList(ids));
    }

    @Override
    public Map<String, Object> getRealTimeInfo(){
        return plcCacheService.getRealDataByTags("水泵","");
    }

    @Override
    public Map<String,List<HisCol>> getEnergyChartAll(Date beginTime, Date endTime){
        Map<String,List<HisCol>> result = new HashMap<String,List<HisCol>>();
        PlcCache plcCache = new PlcCache();
        plcCache.setCacheTag("水泵");
        List<PlcCache> plcCacheList = plcCacheService.selectPlcCacheList(plcCache);
        for(PlcCache plcCache1 : plcCacheList){
            List<HisCol> hisColList=plcCacheService.getHisColListByCode(plcCache1,beginTime, endTime, 1);
            result.put(plcCache1.getCacheDescr(),hisColList);
        }

        return result;
    }
    @DataSource(value = DataSourceType.SLAVE)
    private List<Map<String, Object>> getHisRowListPage(List<String> tables, List<String> codeList, Date beginTime, Date endTime, Integer timeTag, Integer pageSize, Integer pageNum){
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
        return energyPwaterStatisitcsMapper.getHisRowListByCodeListPage(tables, codeList,beginTime, endTime, timeTag, pageSize, pageSize * (pageNum - 1));
    }
    private int countHisRowList(List<String> tables, Date beginTime, Date endTime, Integer timeTag){
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
        return energyPwaterStatisitcsMapper.countHisRowList(tables, beginTime, endTime, timeTag);
    }
    @DataSource(value = DataSourceType.SLAVE)
    private List<Map<String, Object>> getHisRowList(List<String> tables, List<String> codeList, Date beginTime, Date endTime, Integer timeTag){
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
        return energyPwaterStatisitcsMapper.getHisRowListByCodeList(tables, codeList,beginTime, endTime, timeTag);
    }
    @Override
    public Map<String, Object> getEnergyHistory(Date beginTime,Date endTime,Integer timeType, Integer pageNum, Integer pageSize){
        PlcCache plcCache = new PlcCache();
        plcCache.setCacheTag("能源");
        List<PlcCache> plcCacheList = plcCacheService.selectPlcCacheList(plcCache);
        StringBuilder checkedParams = new StringBuilder();
        checkedParams.append("dt");
        if(plcCacheList!=null && plcCacheList.size()>0){
            for(PlcCache plcCache1 : plcCacheList){
                checkedParams.append(",").append(plcCache1.getCacheCode());
            }
        }else{
            return null;
        }
        Map<String, Object> res = new HashMap<>();

        List<Map<String, Object>> rows = new ArrayList<>();
        int total = 0;
        if (beginTime == null || endTime == null) {
            beginTime = DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, -1);
            endTime = DateUtil.endOfDay(new Date());
        }
        int timeTag = Convert.toInt(timeType, 1);
        Date startFormat = DateUtil.parseDate(DateUtil.formatDate(beginTime));
        Date endFormat = DateUtil.parseDate(DateUtil.formatDate(endTime));
        try {
//            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
            List<String> tables = new ArrayList<>();
            while (startFormat.getTime() <= endFormat.getTime()) {
                String table = "plc_his_row_" +plcCacheList.get(0).getCacheSaveTable() + "_" + DateUtil.format(startFormat, "yyyyMMdd");
                if (plcCacheService.checkTable(table)) {
                    tables.add(table);
                }
                startFormat = DateUtil.offset(startFormat, DateField.DAY_OF_MONTH, 1);
            }
            if (!tables.isEmpty()) {
                List<String> codeList = new ArrayList<>();
                if(!checkedParams.toString().equals("") && !checkedParams.toString().equals("null")){
                    String[] splitString = checkedParams.toString().split(",");
                    for (int i = 0; i < splitString.length; i++) {
                        codeList.add(StrUtil.toUnderlineCase(splitString[i]));
                    }
                }
//                rows = energyMediumServeMapper.getHisRowListByCodeListPage(tables, codeList,beginTime, endTime, timeTag, pageSize, pageSize * (pageNum - 1));
                rows = getHisRowListPage(tables, codeList,beginTime, endTime, timeTag, pageSize, pageNum);
                for (int i = 0; i < rows.size(); i++) {
                    Map<String, Object> row = rows.get(i);
                    row.put("dt", DateUtil.formatDateTime((Convert.toDate(row.get("dt")))));
                }
//                total = energyMediumServeMapper.countHisRowList(tables, beginTime, endTime, timeTag);
                total = countHisRowList(tables, beginTime, endTime, timeTag);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DynamicDataSourceContextHolder.clearDataSourceType();
        }

        res.put("rows", rows);
        res.put("total", total);
        res.put("plcCacheList",plcCacheList);
        return res;
    }

    @Override
    public String exportEnergyHistory(Date beginTime,Date endTime,Integer timeType) {
        PlcCache plcCache = new PlcCache();
        plcCache.setCacheTag("能源");
        List<PlcCache> plcCacheList = plcCacheService.selectPlcCacheList(plcCache);
        StringBuilder checkedParams = new StringBuilder();
        checkedParams.append("dt");
        if(plcCacheList!=null && plcCacheList.size()>0){
            for(PlcCache plcCache1 : plcCacheList){
                checkedParams.append(",").append(plcCache1.getCacheCode());
            }
        }else{
            return null;
        }
        List<Map> mapList = new ArrayList<>();
        List<Map<String, Object>> rows = new ArrayList<>();
        if (beginTime == null || endTime == null) {
            beginTime = DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, -1);
            endTime = DateUtil.endOfDay(new Date());
        }
        int timeTag = Convert.toInt(timeType, 1);
        Date startFormat = DateUtil.parseDate(DateUtil.formatDate(beginTime));
        Date endFormat = DateUtil.parseDate(DateUtil.formatDate(endTime));
        try {
//            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
            List<String> tables = new ArrayList<>();
            while (startFormat.getTime() <= endFormat.getTime()) {
                String table = "plc_his_row_" +plcCacheList.get(0).getCacheSaveTable() + "_" + DateUtil.format(startFormat, "yyyyMMdd");
                if (plcCacheService.checkTable(table)) {
                    tables.add(table);
                }
                startFormat = DateUtil.offset(startFormat, DateField.DAY_OF_MONTH, 1);
            }
            if (!tables.isEmpty()) {
                List<String> codeList = new ArrayList<>();
                if(!checkedParams.toString().equals("") && !checkedParams.toString().equals("null")){
                    String[] splitString = checkedParams.toString().split(",");
                    for (int i = 0; i < splitString.length; i++) {
                        codeList.add(StrUtil.toUnderlineCase(splitString[i]));
                    }
//                    rows = energyMediumServeMapper.getHisRowListByCodeList(tables, codeList,beginTime, endTime, timeTag);
                    rows = getHisRowList(tables, codeList,beginTime, endTime, timeTag);
                    for (int i = 0; i < rows.size(); i++) {
                        Map<String, Object> row = rows.get(i);
                        Map<String, Object> map = new LinkedHashMap<>();
                        map.put("日期", DateUtil.formatDateTime(Convert.toDate(row.get("dt"))));
                        for(PlcCache plcCache1: plcCacheList){
                            if(row.containsKey(StrUtil.toCamelCase(plcCache1.getCacheCode()))){
                                map.put(plcCache1.getCacheDescr(), row.get(StrUtil.toCamelCase(plcCache1.getCacheCode())));
                            }
                        }
                        mapList.add(map);
                    }
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DynamicDataSourceContextHolder.clearDataSourceType();
        }

        String timeTypeStr = "";
        if (timeType == 1) timeTypeStr = "秒";
        if (timeType == 2) timeTypeStr = "分钟";
        if (timeType == 3) timeTypeStr = "小时";
        if (timeType == 4) timeTypeStr = "日";

        ExcelWriter exportWriter = ExcelUtil.getBigWriter();
        exportWriter.write(mapList, true);
        exportWriter.autoSizeColumnAll();
        String filename = IdUtils.fastSimpleUUID() + "_" + "能源历史" + timeTypeStr + "报表_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
        try {
            OutputStream out = new FileOutputStream(getAbsoluteFile(ProjectConfig.getDownloadPath(), filename));;
            exportWriter.flush(out, true);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException("导出失败");
        } finally {
            exportWriter.close();
        }
        return filename;
    }
}
